package com.thunder.ktv.scoreengine2test.utils;

import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * Created by chengkai on 19-1-11.
 */

public class FileUtil {

    public static String readString(File file)
    {
        if(file == null){
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        int fileLength = (int) file.length();
        byte[] buffer = new byte[fileLength];
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(file);
            if(fileInputStream == null){
                return "";
            }
            while (fileInputStream.read(buffer) > 0){
                stringBuilder.append(new String(buffer).trim());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                fileInputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString().trim();
    }

    public static JSONObject readJson(File file)
    {
        try {
            return new JSONObject(readString(file));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static boolean appendString2File(String str,File file){
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(file, "rw");
            randomAccessFile.seek(file.length());
            randomAccessFile.write(str.getBytes());
        }catch (IOException e){
            return false;
        }finally {
            try {
                assert randomAccessFile != null;
                randomAccessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }


    public static void forEachFile(File file,final Consumer<File> action) {
        try {
            if(isDir(file)){
                Arrays.stream(Objects.requireNonNull(file.listFiles()))
                        .filter(FileUtil::canRead)
                        .forEach(file12 -> FileUtil.forEachFile(file12,action));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        action.accept(file);
    }

    public static boolean isFile(File file) {
        try {
            return Stream.of(file)
                    .filter(File::exists)
                    .filter(File::isFile)
                    .filter(FileUtil::canRead)
                    .count() == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean isDir(File dir) {
        try {
            return Stream.of(dir)
                    .filter(File::exists)
                    .filter(File::isDirectory)
                    .filter(FileUtil::canRead)
                    .count() == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean newDir(File dir) {
        try {
            return Stream.of(dir)
                    .filter(f -> !f.exists())
                    .filter(File::mkdir)
                    .filter(FileUtil::isDir)
                    .count() == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean newFile(File file) {
        try {
            return Stream.of(file)
                    .filter(f -> {
                        try {
                            return f.createNewFile();
                        } catch (IOException e) {
                            e.printStackTrace();
                            return false;
                        }
                    })
                    .filter(FileUtil::isFile)
                    .count() == 1;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static boolean del(File file)
    {
        forEachFile(file,file1 -> file1.delete());
        return file.exists();
    }

    public static List<String> readLines(File file)
    {
        List<String> list = new ArrayList<>();
        if(!isFile(file))
            return list;
        String line;
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            while ((line = reader.readLine()) != null){
                list.add(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    public static String readStr(File file)
    {
        StringBuilder builder = new StringBuilder();
        List<String> strings = readLines(file);
        Stream.of(strings).forEach(s -> builder.append(s));
        return builder.toString();
    }

    private static final String TAG = "FileUtil";
    public static boolean canRead(File file)
    {
        boolean ret = file.canRead();
        if(!ret){
            Log.w(TAG, "canRead: " + file.getName() + " is false");
        }
        return ret;
    }
    public static boolean writeLines(File file,List<String> list)
    {
        if(!isFile(file))
            return false;
        final BufferedWriter[] writer = {null};
        try {
            writer[0] = new BufferedWriter(new FileWriter(file));
            list.forEach(s -> {
                try {
                    writer[0].write(s);
                    writer[0].newLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                writer[0].close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    public static boolean addLines(File file,List<String> list)
    {
        Set set = new HashSet(FileUtil.readLines(file));
        set.addAll(list);
        return FileUtil.writeLines(file,new ArrayList<String>(set));
    }

    public static byte[] readBytes(String fileName) {
        File file = new File(fileName);
        byte[] bytes = new byte[(int) file.length()];
        try (FileInputStream fis = new FileInputStream(file)) {
            fis.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }
}
